package main

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os/exec"
	"strings"
	"time"
)

type Session struct {
	baseURL string
	cookie  string
	client  *http.Client
}

func NewSession(baseURL string) *Session {
	return &Session{
		baseURL: baseURL,
		client: &http.Client{
			Timeout: 10 * time.Second,
		},
	}
}

func (s *Session) getLD() (string, error) {
	req, err := http.NewRequest("GET", s.baseURL+"/goform/goform_get_cmd_process?isTest=false&cmd=LD&_=1685123456789", nil)
	if err != nil {
		return "", err
	}
	req.Header.Set("Referer", "http://"+*IP+":8080")

	resp, err := s.client.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	//fmt.Println("getLD:",string(body))

	var result struct {
		LD string `json:"LD"`
	}
	if err := json.Unmarshal(body, &result); err != nil {
		return "", err
	}

	return result.LD, nil
}

func (s *Session) getUFIInfo() (string, string, error) {
	req, err := http.NewRequest("GET", s.baseURL+"/goform/goform_get_cmd_process?multi_data=1&isTest=false&cmd=Language,cr_version,wa_inner_version&multi_data=1&_=1685123456789", nil)
	if err != nil {
		return "", "", err
	}
	req.Header.Set("Referer", "http://"+*IP+":8080")

	resp, err := s.client.Do(req)
	if err != nil {
		return "", "", err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", "", err
	}
	//fmt.Println("getUFIInfo:",string(body))

	var result struct {
		CrVersion      string `json:"cr_version"`
		WaInnerVersion string `json:"wa_inner_version"`
	}
	if err := json.Unmarshal(body, &result); err != nil {
		return "", "", err
	}

	return result.WaInnerVersion, result.CrVersion, nil
}

func (s *Session) getRD(cookie string) (string, error) {
	req, err := http.NewRequest("GET", s.baseURL+"/goform/goform_get_cmd_process?isTest=false&cmd=RD&_=1685123456789", nil)
	if err != nil {
		return "", err
	}
	req.Header.Set("Referer", "http://"+*IP+":8080")
	req.Header.Set("Cookie", cookie)

	resp, err := s.client.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	//fmt.Println("getRD:",string(body))

	var result struct {
		RD string `json:"RD"`
	}
	if err := json.Unmarshal(body, &result); err != nil {
		return "", err
	}

	return result.RD, nil
}

func (s *Session) processAD(cookie string) (string, error) {
	waInnerVersion, crVersion, err := s.getUFIInfo()
	if err != nil {
		return "", err
	}

	parsedInfoHex := SHA256(waInnerVersion + crVersion)

	RD, err := s.getRD(cookie)
	if err != nil {
		return "", err
	}

	return SHA256(parsedInfoHex + RD), nil
}

func SHA256(txt string) string {
	hashed := sha256.Sum256([]byte(txt))
	hashedHex := hex.EncodeToString(hashed[:])
	return strings.ToUpper(hashedHex)
}

func (s *Session) Login(password string) (string, error) {
	LD, err := s.getLD()
	if err != nil {
		return "", err
	}
	pwd := SHA256(SHA256(password) + LD)

	data := url.Values{
		"goformId": {"LOGIN"},
		"isTest":   {"false"},
		"password": {pwd},
	}
	//fmt.Println(data)
	req, err := http.NewRequest("POST", s.baseURL+"/goform/goform_set_cmd_process", bytes.NewBufferString(data.Encode()))
	if err != nil {
		return "", err
	}
	req.Header.Set("Referer", "http://"+*IP+":8080")
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")

	resp, err := s.client.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	//fmt.Println("Login:",string(body))
	if string(body) != `{"result":0}` {
		return "", fmt.Errorf("密码错误")
	}
	cookie := resp.Header.Get("Set-Cookie")
	if cookie == "" {
		return "", fmt.Errorf("获取cookie失败")
	}

	s.cookie = cookie
	return cookie, nil
}

func (s *Session) SendSMS(content, number string) (string, error) {
	if s.cookie == "" {
		return "", fmt.Errorf("没有登录")
	}

	AD, err := s.processAD(s.cookie)
	if err != nil {
		return "", err
	}

	encodedContent := gsmEncode(content)

	data := url.Values{
		"goformId":    {"SEND_SMS"},
		"isTest":      {"false"},
		"AD":          {AD},
		"Number":      {number},
		"MessageBody": {encodedContent},
	}
	//fmt.Println(data)
	req, err := http.NewRequest("POST", s.baseURL+"/goform/goform_set_cmd_process", bytes.NewBufferString(data.Encode()))
	if err != nil {
		return "", err
	}
	req.Header.Set("Referer", "http://"+*IP+":8080")
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("Cookie", s.cookie)

	resp, err := s.client.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	//fmt.Println("SendSMS:",string(body))

	return string(body), nil
}

func (s *Session) usbPort(number string) (string, error) {
	if s.cookie == "" {
		return "", fmt.Errorf("没有登录")
	}

	AD, err := s.processAD(s.cookie)
	if err != nil {
		return "", err
	}

	data := url.Values{
		"goformId":        {"USB_PORT_SETTING"},
		"isTest":          {"false"},
		"AD":              {AD},
		"usb_port_switch": {number},
	}
	//fmt.Println(data)
	req, err := http.NewRequest("POST", s.baseURL+"/goform/goform_set_cmd_process", bytes.NewBufferString(data.Encode()))
	if err != nil {
		return "", err
	}
	req.Header.Set("Referer", "http://"+*IP+":8080")
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("Cookie", s.cookie)

	resp, err := s.client.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	//fmt.Println("usbPort:",string(body))
	if string(body) != `{"result":"success"}` {
		return "", fmt.Errorf(string(body))
	}

	return string(body), nil
}

func gsmEncode(text string) string {
	var encoded []byte
	for _, r := range text {
		if r <= '\uFFFF' {
			encoded = append(encoded, byte(r>>8), byte(r))
		} else {
			codePoint := int(r)
			highSurrogate := 0xD800 + ((codePoint - 0x10000) >> 10)
			lowSurrogate := 0xDC00 + ((codePoint - 0x10000) & 0x3FF)
			encoded = append(encoded, byte(highSurrogate>>8), byte(highSurrogate), byte(lowSurrogate>>8), byte(lowSurrogate))
		}
	}
	return hex.EncodeToString(encoded)
}

var IP *string

func main() {
	// 定义命令行参数
	IP = flag.String("ip", "192.168.0.1", "设备后台地址")
	pwd := flag.String("pwd", "admin", "设备管理密码")
	port := flag.String("port", "5555", "需要打开的adb端口")

	// 解析命令行参数
	flag.Parse()

	// 打印参数值
	fmt.Println("地址:", *IP)
	fmt.Println("密码:", *pwd)
	fmt.Println("端口:", *port)

	session := NewSession("http://" + *IP + ":8080")

	// 登录
	_, err := session.Login(*pwd)
	if err != nil {
		fmt.Printf("登录失败: %v\n", err)
		return
	}
	fmt.Println("登陆成功")

	// // 发送短信
	// response, err := session.SendSMS("cxll", "10000")
	// if err != nil {
	// 	fmt.Printf("Send SMS failed: %v\n", err)
	// 	return
	// }
	// fmt.Printf("Send SMS successful. Response: %s\n", response)
	// fmt.Println(gsmEncode("cxll"))

	err = execCommand("/system/bin/setprop", "service.adb.tcp.port", *port)
	if err != nil {
		fmt.Printf("打开adb端口失败: %v\n", err)
		return
	}
	fmt.Println("已打开adb端口")

	_, err = session.usbPort("0")
	if err != nil {
		fmt.Printf("关闭adbd失败: %v\n", err)
		return
	}
	_, err = session.usbPort("1")
	if err != nil {
		fmt.Printf("打开adbd失败: %v\n", err)
		return
	}
	fmt.Println("已重启adbd")
}

func execCommand(command string, args ...string) error {
	// 创建命令对象
	cmd := exec.Command(command, args...)

	// 创建缓冲区来存储命令的标准输出和标准错误输出
	var out bytes.Buffer
	var errOut bytes.Buffer
	cmd.Stdout = &out
	cmd.Stderr = &errOut

	// 执行命令
	err := cmd.Run()
	if err != nil {
		// fmt.Printf("执行命令: %s %s\n", command, strings.Join(args, " "))
		// fmt.Println("执行失败:", err)
		// fmt.Println("错误输出:", errOut.String())
		return err
	}

	// 打印命令及其输出
	if out.String() != "" {
		// fmt.Printf("执行命令: %s %s\n", command, strings.Join(args, " "))
		// fmt.Println("输出:", out.String())
	}
	// fmt.Printf("成功执行命令: %s %s\n", command, strings.Join(args, " "))
	return nil
}
